#pragma once

#include "Singleton.h"
#include "System.h"
#include "IEntityController.h"
#include "Entity.h"
#include "World.h"
#include "CameraNode.h"

#define Game	GameApplication::getSingleton()

class GameApplication : public Singleton<GameApplication>
{
public:
	GameApplication();
	// Entity
	void RegisterEntity( HashedString name, Pointer<Entity> entity );
	Pointer<Entity> RetrieveEntity( HashedString name );
	void RemoveEntity( HashedString name );
	void RemoveEntity( Entity* entity );
	bool EntityExists( Entity* entity );
	// World
	void CreateWorld( HashedString name );
	Pointer<Pathing::World> RetrieveWorld( HashedString name );
	// Texture filenames **note: not very nice solution
	void RegisterTexture( std::string filename );
	// Selectables
	void RegisterSelectable( RigidBody* selectable );
	void RemoveSelectable( RigidBody* selectable );
	Entity* Select( int x, int y );
	Entity* Select( int x, int y, Maths::Vector3D& point );
	// Controllers
	void RegisterController( Pointer<IEntityController> controller );
	void RemoveController( IEntityController* controller );
	void RemoveController( Entity* entity );
	// Entity Groups
	std::list<Entity*>& getEntityGroup( HashedString name );
	void RegisterEntityToGroup( HashedString name, Entity* entity );
	void RemoveEntityFromGroups( Entity* entity );
	// System functions - avoid use
	Entity::Map_t& _getAllEntities();
	Pointer<System>& _getSelectables();
	std::vector<std::string>& _getTextureStrings();
	IEntityController::Vector_t& _getControllers();
	Pathing::World::Map_t& _getWorlds();
	Pointer<CameraNode>& _getMainCamera();
protected:
	// Entity groups
	std::map<HashedString, std::list<Entity*>> m_entityGroups;
	Pointer<CameraNode> m_mainCamera;
	// selectable system; used for raycast from pointer
	Pointer<System> m_selectables;
	// list of all controllers
	IEntityController::Vector_t m_controllers;
	// list of textures
	std::vector<std::string> m_textureStrings;
	// list of all entities, by name
	Entity::Map_t m_entities;
	// Worlds - containers of obstacles, by name
	Pathing::World::Map_t m_worlds;
};